<?php
//
//  VictoryCMS - Content managment system and framework.
//  Copyright (C) 2009  Lewis Gunsch
//
//  This file is part of VictoryCMS.
//
//  VictoryCMS is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  VictoryCMS is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with VictoryCMS.  If not, see <http://www.gnu.org/licenses/>.

/**
 * VictoryCMS - SqlSet
 * 
 * @license http://www.gnu.org/licenses/gpl.html
 * @author Lewis Gunsch
 * @filesource
 * @package DBAbstraction
 */

/**
 * This class represents a set of SQL queries. Each query is identified
 * by a name, and has printf formatting tokens for the information that
 * should be replaced by concrete information.
 * <p>
 * <ul>
 * <li>Example: $this->set["version"] = "SELECT version()";
 * <li>Example: $this->set["create_test_table"] = "CREATE TABLE ".$dbprefix."test_table 
 * ( name VarChar(30), data TEXT )"
 * <li>$this->set["put_row"] = "INSERT INTO ".$dbprefix."test_table (name, data) VALUES (\"%s\", \"%s\")";
 * </ul>
 *
 * @package DBAbstraction
 */
abstract class SqlSet {

	/** List of query's indexed with a unique name **/
	protected $set;

	/**
	 * Initialize the new SqlQuerySet. This will call the initQuerySet
	 * function to prebuild the $set array.
	 */
	public function __construct() {
		$set = array();
		$this->initQuerySet();
	}

	/**
	 * Construct a query identified by $name, and bind with
	 * the $dataset query parameters, both columns and corresponding
	 * tuples after cleaning the data. The dataset should be formatted
	 * by array key's being the columns and the value being the
	 * corresponding tuple value. This will locate the query identified
	 * by $name, put in the data from dataset after using the VcmsDB
	 * instance to clean the data and return the newly created string
	 * to be used in an sql query. If any information is missing, or there
	 * is a mismatch of printf formatting tokens and the dataset then
	 * an InvalidDatasetException will be thrown.
	 *
	 * @param $name The name identifier of the query requested.
	 * @param $dataset The data to be merged with the query string (column => tuple value).
	 * @return String containing the sql query and the data provided
	 *
	 * @TODO This function should throw a InvalidDatasetException
	 */
	public function getAssembledQuery($name, array $dataset = NULL) {
		$query = $this->getEmptyQuery($name);
		if ($dataset != NULL) {
			if (! is_array($dataset)) {
				throw new Exception("$dataset is not an array!");
			}
			
			$this->putInPrefix($dataset);
			
			// put the query in the beginning of the dataset for call_user_func_array
			// to use when calling sprintf
			array_unshift($dataset, $query);
			try {
				$assembled = call_user_func_array( 'sprintf', $dataset);
			} catch (Exception $ex) {
				throw new Exception("Could not assemble query properly: ".
					$ex->getMessage()."!");
			}
		} else {
			$assembled = $query;
		}
		echo "SqlSet query: \"".$assembled."\" <br/>";
		return $assembled;
	}

	/**
	 * Returns the array string identified by name with the printf formatt
	 * tokens in the correct places. There should be formatting tokens
	 * for the column names, and the corresponding information.
	 * @param $name The name identifier of the query requested.
	 * @return SQL query with printf formatting tokens.
	 * 
	 * @TODO Make custom exceptions
	 */
	public function getEmptyQuery($name) {
		if (empty($name)) {
			throw new Exception("Query must be identified by a non-empty name.");
		}
		if (empty($this->set[$name])) {
			throw new Exception("Query identified by \"$name\" was found empty!");
		}
		if (! is_array($this->set)) {
			return "";
		}
		return $this->set[$name];
	}

	private function putInPrefix(array $dataset) {
		
	}
	/**
	 * This is called by the constructor to initialize the set array.
	 * Each entry should be identified by a unique name, and should have printf
	 * formatting tokens where appropiate for inserting data. The database type 
	 * set in VcmsSettings should be used to determine the SQL style to use 
	 * for the queries. The database table prefix should also be used when 
	 * creating database tables.
	 */
	abstract protected function initQuerySet();

}
?>